package com.snowflake.ecatalog.service.admin;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Path;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springside.modules.persistence.SearchFilter;

import com.google.common.collect.Lists;
import com.snowflake.ecatalog.contant.Status;
import com.snowflake.ecatalog.entity.Company;
import com.snowflake.ecatalog.entity.CompanyCategory;
import com.snowflake.ecatalog.entity.CompanyLinkman;
import com.snowflake.ecatalog.repository.CompanyCategoryDao;
import com.snowflake.ecatalog.repository.CompanyDao;
import com.snowflake.ecatalog.util.LoginUtil;

@Service
@Transactional(readOnly = true)
public class CompanyService {
	@Autowired
	private CompanyDao companyDao;
	@Autowired
	private CompanyCategoryDao companyCategoryDao;

	public Company getCompany(Long id) {
		return companyDao.findOne(id);
	}

	@Transactional(readOnly = false)
	public void saveCompany(Company company) {
		company.setCreator(LoginUtil.getCurrentUser());
		company.setCreatedTime(new Date());
		company.setStatus(Status.ENABLE);
		// 设置联系人中的企业
		List<CompanyLinkman> companyLinkmans = company.getCompanyLinkmans();
		for (CompanyLinkman companyLinkman : companyLinkmans) {
			companyLinkman.setCompany(company);
		}
		// 过滤CompanyCategory空的Id
		filterNullCompanyCategoryId(company);

		companyDao.save(company);
	}

	@Transactional(readOnly = false)
	public void updateCompany(Company company) {
		// 过滤CompanyCategory空的Id
		filterNullCompanyCategoryId(company);

		company.setLastModifier(LoginUtil.getCurrentUser());
		company.setLastModifiedTime(new Date());
		companyDao.save(company);
	}

	@Transactional(readOnly = false)
	public void deleteCompany(Long id) {
		companyDao.delete(id);
	}

	public List<Company> getEnabledCompanyByCategory(Long categoryId, List<Long> exludeIdList) {
		List<Company> companyList = null;
		if (CollectionUtils.isNotEmpty(exludeIdList)) {
			companyList = companyDao.findByCompanyCategorysIdAndStatusAndIdNotIn(categoryId, Status.ENABLE,
					exludeIdList);
		} else {
			companyList = companyDao.findByCompanyCategorysIdAndStatus(categoryId, Status.ENABLE);
		}
		return companyList;
	}

	public List<Company> getAllCompany() {
		return (List<Company>) companyDao.findAll();
	}

	public Page<Company> getCompanys(Long categoryId, Map<String, Object> filterParams, int pageNumber, int pageSize) {
		PageRequest pageRequest = buildPageRequest(pageNumber, pageSize);
		Specification<Company> spec = buildSpecification(categoryId, filterParams);
		return companyDao.findAll(spec, pageRequest);
	}

	@Transactional(readOnly = false)
	public void enableCompany(Long id) {
		companyDao.changeStatus(Status.ENABLE, id);
	}

	@Transactional(readOnly = false)
	public void disableCompany(Long id) {
		companyDao.changeStatus(Status.DISABLE, id);
	}

	public boolean isCompanyLinkedProfiled(Long companyId) {
		Company company = getCompany(companyId);
		return CollectionUtils.isNotEmpty(company.getProfiles());
	}

	/**
	 * 创建分页请求.
	 */
	private PageRequest buildPageRequest(int pageNumber, int pagzSize) {
		return new PageRequest(pageNumber - 1, pagzSize);
	}

	/**
	 * 创建动态查询条件组合.
	 */
	private Specification<Company> buildSpecification(Long categoryId, Map<String, Object> filterParams) {
		final Map<String, SearchFilter> filters = SearchFilter.parse(filterParams);
		// filters.put("std.id", new SearchFilter("std.id", Operator.EQ,
		// categoryId));
		// Specification<Company> spec =
		// DynamicSpecifications.bySearchFilter(filters.values(),Company.class);
		final List<Long> companyIds = getCompanyIdsOfCategory(categoryId);
		Specification<Company> spec = new Specification<Company>() {
			@Override
			public Predicate toPredicate(Root<Company> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
				List<Predicate> orPredicates = Lists.newArrayList();
				for (Long id : companyIds) {
					orPredicates.add(builder.equal((Path) root.get("id"), id));
				}
				List<Predicate> andPredicates = Lists.newArrayList();
				if (filters.containsKey("name")) {
					andPredicates.add(builder.like((Path) root.get("name"), "%" + filters.get("name").value + "%"));
				}
				if (filters.containsKey("number")) {
					andPredicates.add(builder.like((Path) root.get("number"), "%" + filters.get("number").value + "%"));
				}
				if (!CollectionUtils.isEmpty(orPredicates)) {
					andPredicates.add(builder.or(orPredicates.toArray(new Predicate[orPredicates.size()])));
				} else {
					andPredicates.add(builder.equal((Path) root.get("id"), -1));
				}
				return builder.and(andPredicates.toArray(new Predicate[andPredicates.size()]));
			}
		};
		return spec;
	}

	private List<Long> getCompanyIdsOfCategory(Long categoryId) {
		List<Long> companyIds = new ArrayList<Long>();
		if (categoryId > 0) {
			CompanyCategory category = companyCategoryDao.findOne(categoryId);
			List<Company> companys = category.getCompanys();
			for (Company c : companys) {
				companyIds.add(c.getId());
			}
		}
		return companyIds;
	}

	// 过滤CompanyCategory空的Id
	private void filterNullCompanyCategoryId(Company company) {
		CollectionUtils.filter(company.getCompanyCategorys(), new org.apache.commons.collections.Predicate() {

			@Override
			public boolean evaluate(Object object) {
				CompanyCategory companyCategory = (CompanyCategory) object;
				return (null != companyCategory.getId());
			}

		});
	}
}
